#pragma once
#ifndef __NEZHACREADFILE_H__
#define __NEZHACREADFILE_H__

#include "NezhaIReadFile.h"
#include "NezhaOS.h"

#include <stdio.h>

#if defined(NZOS_WIN32)
#include <windows.h>
#elif defined(NZOS_IOS)
#	include <aio.h>
#   include <queue>
#   include <vector>
#endif

namespace Nezha
{
	namespace stream
	{
		class CFile;

		class FOUNDATION_ENTRY CReadFile : public IReadFile
		{
		public:
			CReadFile(const wchar_t* fileName, bool headerObfuscated = false);
			CReadFile(const char* fileName, bool headerObfuscated = false);
	
			virtual IReadFile* clone(bool keepPos = true) const;

			virtual ~CReadFile();

			virtual int read(void* buffer, u32 sizeToRead);

			virtual bool readAsync(void* buffer, u32 sizeToRead, Callback callback, void* arg);

			virtual bool readAsync(void* buffer, u32 sizeToRead, long finalPos, Callback callback, void* arg);

			virtual bool seek(long finalPos, bool relativeMovement = false);

			virtual long getSize() const;

			virtual void* getBuffer(long* size)
			{
				long sizeFile = getSize();

				if (sizeFile >0)
				{
				char* fileBuffer = NULL;
				fileBuffer = NZ_New char[sizeFile];
				read(fileBuffer, sizeFile);
				*size = sizeFile;
				return fileBuffer;
				}
				
				return 0;
			}

			bool isOpen() const;

			virtual long getPos() const;

			virtual const char* getFileName() const;

			virtual const char* getFullPath() const;

		private:

			void openFile();
	
			CFile* mFilePtr;

			long mFileSize;
			String mFilename;
			bool mHeaderObfuscated;

#if defined(NZOS_WIN32)
		public:

			struct SAsyncReadDesc
			{
				CReadFile* Readfile;
				Callback Callback;
				void* Arg;
				HANDLE FileHandle;
				OVERLAPPED Overlapped;
			};

		private:
			static void WINAPI asyncReadCallback(DWORD error, DWORD transfered, LPOVERLAPPED overlapped);
#elif defined(NZOS_IOS)
		public:

			struct SAsyncReadDesc
			{
				CReadFile* Readfile;
				Callback Callback;
				void* Arg;
				aiocb AioStruct;
			};

		private:
			static void aioSignalDone(int sig);
			static std::queue<SAsyncReadDesc*> AioReadInQueue;
			static SAsyncReadDesc* AioReadInProgress;
			static struct sigaction OriginalSigAction;
#endif
		};
	};
};

#endif // __NEZHACREADFILE_H__